package scanner;

import java.io.IOException;
import java.util.Iterator;

import parser.StringMatch;
import parser.StringMatchSet;

import cs3240.regex.automaton.DFATable;

/**
 * This class simply holds the main
 * method for the project, which runs
 * through the necessary code to generate 
 * a Table-Driven DFA for a specification file,
 * and then identify tokens in a code file.
 *  
 * @author Dilan Manatunga
 *
 */
public class RegexProject {

	/**
	 * The main function that is run when the project is run.
	 * This function must at least have two inputs of the name of 
	 * the specification file and the name of the code file. 
	 * It also takes in optional arguments for the name of the 
	 * file to print the token statistics to, the name of the file to
	 * print the DFA Table to, and the name of the file to print the
	 * minimal DFA Table to. If those arguments are not specified, the 
	 * DFA output file will be called "dfa.txt", and the minimal DFA 
	 * output file will be "minimalDFA.txt".
	 * 
	 * This function first calls a scanner generator to parse the
	 * specification file for Character Classes and Token definitions.
	 * The scanner generator will then return a DFA table to identify
	 * the specified tokens. After the scanner generator has run, the 
	 * function will print out the identified Character Classes and 
	 * their values, the scanner generated DFA table, the minimal DFA
	 * table for the DFA generated by the scanner. It will then take 
	 * the generated minimal DFA table, and pass it to a driver program 
	 * which will then attempt to identify the tokens in the code file.
	 * After the driver has completed running, the function will print 
	 * out a list of the tokens and their identified type (if the
	 * token was identified).
	 * 
	 * @param args a list of command line inputs
	 */
	public static StringMatchSet getTokens(String[] args) {
		//System.out.println("Program Start");
		
		String spec_filename = "";  // The specification file name
		String code_filename = "";  // The code file name
		String dfa_file = "dfa.txt";  // The default name of the file to store the generated DFA
		String minimalDFA_file = "minimalDFA.txt"; // The default name of the file to store the minimal DFA
		String tokenStats_file = "tokenStats.txt"; // the default name for the token stats file
		// Save the inputed file names to the necessary variables
		switch (args.length) {
			case 5:
				minimalDFA_file = args[5];
			case 4:
				dfa_file = args[4];
			case 3:
				tokenStats_file = args[3];
			case 2:
				spec_filename = args[0];
				code_filename = args[1];
				break;
			default:
				// Not enough arguments provided
				System.err.println("Please provide at least two arguments:\n\t1. filename of specification file\n\t2. filename of possible tokens file\n\t3. (Optional) Name of the file to store Token Statistics to\n\t4. (Optional) Name of file to store DFA Table\n\t5. (Optional) Name of file to store minimal DFA Table");
				return null;
		}
		
		// Create a scanner generator for the specification file name
		ScannerGen scannerGen = new ScannerGen(spec_filename);
		DFATable dfa = null;
		try {
			//System.out.println("Running Scanner Generator...");
			dfa = scannerGen.run();  // Run the scanner generator and save the generated DFA
			//System.out.println("Scanner Generation Complete");
		} catch (IOException e) {
			System.err.println("IO Exception has occurred while reading specification file.");
			return null;
		} catch (Exception e) {
			System.err.println(e);
			return null;
		}
		
		//System.out.println("===========Character Classes==========");
		// Print out the identified Character Classes
		//scannerGen.printCharClasses();
		//System.out.println("======================================");
		
//		System.out.println("===============Regex DFA==============");
//		// Print out the identified DFA
//		System.out.print(dfa.toString());
//		System.out.println("======================================");
		
		// Print the DFA Table to a file
		//System.out.println("Printing DFA Table to File...");
		dfa.printToFile(dfa_file);
		
		//System.out.println("Converting DFA to Minimal DFA...");
		// Convert the DFA to its minimal version
		DFATable minimalDFA = dfa.toMinimalDFA();
		
//		System.out.println("==============Minimal DFA=============");
//		// Print out the minimal DFA
//		System.out.print(minimalDFA.toString());
//		System.out.println("======================================");

		// Print the minimal DFA Table to a file
		//System.out.println("Printing Minimal DFA Table to File...");
		minimalDFA.printToFile(minimalDFA_file);
		
		
		//System.out.println("==========DFA vs. Minimal DFA=========");
		// Print out the DFA size versus the minimal DFA size
		//System.out.format("DFA Size: %d\nMinimal DFA Size: %d\n", dfa.getTableSize(), minimalDFA.getTableSize());
		//System.out.println("======================================");
		
		// Create a driver with the given code file name and pass in the minimal DFA table
		Driver driver = new Driver(code_filename, minimalDFA);
		try {
			//System.out.println("Running Driver...");
			driver.run(); // Run the driver to identify token
			//System.out.println("Driver Token Identification Compelete");
			//Iterator<StringMatch> iter = driver.stringMatches.iterator();
			//while(iter.hasNext())
			//{
				//StringMatch sm = iter.next();
				//System.out.println("String: "+sm.value+" FileName: "+sm.fileName+" Line#: "+sm.lineNumber+" StartIndex: "+sm.startIndex+" EndIndex: "+sm.endIndex);
			//}
		} catch (IOException e) {
			System.err.println("IO Exception has occurred while reading file.");
			return null;
		}
		StringMatchSet retval = new StringMatchSet();
		retval.matchSet = driver.stringMatches;
		
		return retval;
//		// Print out the stats for Token identification
//		System.out.println("===============Token IDs==============");
//		driver.printStats();
//		System.out.println("======================================");
		
		// Print token statistics to file
		//System.out.println("Printing Token Statistics To File...");
		//driver.printStatsToFile(tokenStats_file);
		
		//System.out.println("Program End");

	}

}
